<?php

namespace app\common\model;
use app\api\model\ServerException;
use app\api\model\TokenException;
use app\api\model\UserException;
use think\facade\Cache;
use think\facade\Db;

class OrderRefund extends Base
{
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = true;

    /**
     * 申请退款信息
     * @param $user
     * @param $order_id
     * @return array
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function reason($user,$order_id){
        $order_id = intval($order_id);
        //订单
        $order = Db::name('order')
            ->where('id','=',$order_id)
            ->where('uid','=',$user['id'])
            ->field('id,type,activity_type,verify_type,status,goods_num,pay_price')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if(in_array($order['status'],[-1,0])){
            throw new UserException('订单未支付，无法申请退款');
        }

        if($order['status']>=3){
            throw new UserException('订单已完成，无法申请退款');
        }

        if($order['status']<=-2){
            throw new UserException('订单已申请退款，请勿重复申请');
        }

        $refund_money = $order['pay_price'];

        //按次核销的
        if($order['verify_type']==2){
            $cal = Db::name('order_goods')
                ->where('order_id','=',$order['id'])
                ->field('sum(num) as num,sum(leave_num) as leave_num')
                ->find();
            if($cal['leave_num']<$cal['num']){
                $refund_money = deal_two_down($refund_money*$cal['leave_num']/$cal['num']);
            }
        }

        $reason = Settings::getSettings(ZFN_SETTINGS_ORDER_REASON);
        $reason = array_values($reason);

        return [
            'order_id'=>$order_id,
            'activity_type'=>$order['activity_type'],
            'refund_money_max'=>$refund_money,
            'reason'=>$reason
        ];
    }

    /**
     * 申请退款提交
     * @param $user
     * @param $order_id
     * @param $reason_id
     * @param $note
     * @param $imgs
     * @return true
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function refundApply($user,$order_id,$reason_id,$note,$imgs){
        //退款原因
        if(empty($reason_id)){
            throw new UserException('请选择申请退款原因');
        }

        $reason = Settings::getSettings(ZFN_SETTINGS_ORDER_REASON);
        if(!isset($reason[$reason_id])){
            throw new UserException('请选择其他退款原因，该退款原因已下架');
        }
        $reason = $reason[$reason_id]['title'];

        $note = reInjectThree($note);
        if($note==''){
            throw new UserException('请输入补充描述，有助于商家更好的处理售后问题');
        }
        if(mb_strlen($note,'utf-8')>'100'){
            throw new UserException('补充描述请勿超过100字');
        }

        if(!is_array($imgs) || count($imgs)<1){
            throw new UserException('请至少上传一张凭证图片');
        }

        if(count($imgs)>3){
            throw new UserException('凭证图片请勿超出3张');
        }

        //订单
        $order = Db::name('order')
            ->where('id','=',$order_id)
            ->where('uid','=',$user['id'])
            ->field('id,merch_id,type,activity_type,verify_type,status,pay_price')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if(in_array($order['status'],[-1,0])){
            throw new UserException('订单未支付，无法申请退款');
        }

        if($order['status']>=3){
            throw new UserException('订单已完成，无法申请退款');
        }

        if($order['status']<=-2){
            throw new UserException('订单已申请售后，请勿重复申请');
        }

        //系统配置
        $system = Settings::getSystem();
        $refund_over_time = time()+($system['refund_over_time']*3600);
        $change = [
            'status'=>'-2',
            'old_status'=>$order['status'],
            'refund_reason'=>$reason,
            'refund_apply_time'=>time(),
            'refund_over_time'=>$refund_over_time
        ];

        //最高退款金额
        $refund_money_max = $order['pay_price'];

        //按次核销的
        if($order['verify_type']==2){
            $cal = Db::name('order_goods')
                ->where('order_id','=',$order['id'])
                ->field('sum(num) as num,sum(leave_num) as leave_num')
                ->find();
            if($cal['leave_num']<$cal['num']){
                $change['is_some_refund'] = 1;
                $change['refund_num']=$cal['leave_num'];

                $refund_money_max = deal_two_down($refund_money_max*$cal['leave_num']/$cal['num']);
            }
        }
        $change['refund_money']=$refund_money_max;

        $save = Db::name('order')
            ->where('id','=',$order_id)
            ->where('status','in',[1,2])
            ->update($change);
        if(!$save){
            throw new ServerException('订单申请状态保存失败');
        }

        $add = self::create([
            'order_id'=>$order_id,
            'note'=>$note,
            'imgs'=>json_encode($imgs)
        ]);
        if(!$add){
            throw new ServerException('退款信息表保存失败');
        }

        //推送给商家处理
        MerchNotice::send($order['merch_id'],'您的店铺有买家申请退款，请及时查看并处理','1',$order_id);
        return true;
    }

    /**
     * 取消退款
     * @param $order_id
     * @param $user
     * @param $merch_id
     * @return void
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function refundCancel($order_id,$user=false){

        $where = [
            ['id','=',$order_id]
        ];

        if($user){
            $where[] = ['uid','=',$user['id']];
        }

        //订单
        $order = Db::name('order')
            ->where($where)
            ->field('id,order_sn,uid,merch_id,type,activity_type,verify_type,status,old_status')
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['status']!=-2){
            throw new UserException('订单非申请退款状态无法驳回，请刷新');
        }

        $change = [
            'status'=>$order['old_status'],
            'refund_money'=>0,
            'refund_apply_time'=>0,
            'refund_over_time'=>0,
            'refund_reason'=>'',
            'is_some_refund'=>0,
            'refund_num'=>0,
        ];

        $save = Db::name('order')
            ->where('id','=',$order_id)
            ->where('status','=',-2)
            ->update($change);
        if(!$save){
            throw new ServerException('订单状态保存失败');
        }

        //删除退款凭证记录
        self::where('order_id','=',$order_id)->delete();

        //不是会员自己取消申请的给会员通知
        if(!$user){
            Notice::systemSend(2,$order['uid'],'退款申请已被驳回',"您的订单{$order['order_sn']}退款申请已被驳回",2,$order['id']);
        }
    }


    /**
     * 线下退款
     * @param $order_id
     * @throws ServerException
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function refundOffline($order_id){
        $where = [
            ['id','=',$order_id]
        ];

        //订单
        $order = Db::name('order')
            ->where($where)
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }

        if($order['status']!=-2){
            throw new UserException('订单非申请退款状态，不可操作，请刷新');
        }

        if($order['refund_over_time']> 0 && $order['refund_over_time']<=time()){
            throw new UserException('已超过退款处理时限');
        }

        $coin = $order['coin'];//要退的积分
        $refund_money = $order['pay_price'];//要退的钱
        $is_some_refund = $order['is_some_refund'];//是否部分退款（按次核销的用了几次退几次）

        if($is_some_refund){
            //计算所有钱
            // 退的钱 = 老的*退款次数/总次数
            // 结算的钱=老的*已用次数/总次数

            $set_percent = ($order['goods_num']-$order['refund_num'])/$order['goods_num'];
            $refund_percent = $order['refund_num']/$order['goods_num'];

            //退钱
            $coin = deal_two_down($coin*$refund_percent);
            $refund_money = deal_two_down($refund_money*$refund_percent);

            //结算

            $change = [
                'status'=>-3,//部分退款
                'receive_time'=>time(),
                'refund_sn'=>'线下退款',
                'refund_money'=>$refund_money,
                'refund_time'=>time(),
                'merch_price'=>deal_two_down($order['merch_price']*$set_percent),
                'coin_send'=>deal_two_down($order['coin_send']*$set_percent),
                'direct_price'=>deal_two_down($order['direct_price']*$set_percent),
                'team2_price'=>deal_two_down($order['team2_price']*$set_percent),
                'team3_price'=>deal_two_down($order['team3_price']*$set_percent),
                'team4_price'=>deal_two_down($order['team4_price']*$set_percent),
                'agent1_price'=>deal_two_down($order['agent1_price']*$set_percent),
                'agent2_price'=>deal_two_down($order['agent2_price']*$set_percent),
            ];

            //更新订单
            $order = array_merge($order,$change);
        }else{
            $change = [
                'status'=>-3,
                'refund_sn'=>'线下退款',
                'refund_money'=>$refund_money,
                'refund_time'=>time(),
            ];
        }

        $save = Db::name('order')
            ->where('id','=',$order_id)
            ->where('status','=',-2)
            ->update($change);
        if(!$save){
            throw new ServerException('订单状态保存失败');
        }

        //积分抵扣退回
        if($coin>0&&$order['uid']>0){
            Finance::addDelUserCoin($order['uid'],$coin,1,"订单{$order['order_sn']}退款返还",6,$order_id);
        }

        //部分退款的订单要结算
        if($is_some_refund){
            Order::orderSettle($order);
        }

        if($order['uid']){
            Notice::systemSend(2,$order['uid'],'订单退款成功',"您的订单{$order['order_sn']}已通过线下退款，请注意查看",2,$order['id']);
        }
    }

    /**
     * 线上退款
     * @param $order_id
     * @param $reason
     * @param int $type 1退款申请超时自动退款 2后台管理员操作退款 3订单有效期过期自动退款
     * @throws ServerException
     * @throws UserException
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    static public function refundOnline($order_id,$reason,$type=1){
        $where = [
            ['id','=',$order_id]
        ];

        //订单
        $order = Db::name('order')
            ->where($where)
            ->find();
        if(!$order){
            throw new UserException('无此订单或无权操作');
        }


        if($order['status']!=-2){
            throw new UserException('订单非申请退款状态，不可操作，请刷新');
        }

        if($type!=1 && $order['refund_over_time']> 0 && $order['refund_over_time']<=time()){
            throw new UserException('已超过退款处理时限');
        }

        $coin = $order['coin'];//积分兑换要退的积分
        $refund_money = $order['pay_price'];//要退的钱
        $is_some_refund = $order['is_some_refund'];//是否部分退款（按次核销的用了几次退几次）

        if($is_some_refund){
            //计算所有钱
            // 退的钱 = 老的*退款次数/总次数
            // 结算的钱=老的*已用次数/总次数

            $set_percent = ($order['goods_num']-$order['refund_num'])/$order['goods_num'];
            $refund_percent = $order['refund_num']/$order['goods_num'];

            //退钱
            $coin = deal_two_down($coin*$refund_percent);
            $refund_money = deal_two_down($refund_money*$refund_percent);

            //结算

            $change = [
                'status'=>-3,//部分退款
                'receive_time'=>time(),
                'refund_money'=>$refund_money,
                'refund_time'=>time(),
                'merch_price'=>deal_two_down($order['merch_price']*$set_percent),
                'coin_send'=>deal_two_down($order['coin_send']*$set_percent),
                'direct_price'=>deal_two_down($order['direct_price']*$set_percent),
                'team2_price'=>deal_two_down($order['team2_price']*$set_percent),
                'team3_price'=>deal_two_down($order['team3_price']*$set_percent),
                'team4_price'=>deal_two_down($order['team4_price']*$set_percent),
                'agent1_price'=>deal_two_down($order['agent1_price']*$set_percent),
                'agent2_price'=>deal_two_down($order['agent2_price']*$set_percent),
            ];

            //更新订单
            $order = array_merge($order,$change);
        }else{
            $change = [
                'status'=>-3,
                'refund_money'=>$refund_money,
                'refund_time'=>time(),
            ];
        }

        //退款单号及余额或积分兑换支付退款
        $refund_sn = $order['refund_sn'];
        if($refund_money>0){
            if($order['pay_type']==3){
                //余额支付
                $res = Finance::addDelUserMoney($order['uid'],$refund_money,1,"订单{$order['order_sn']}退款退回",5,$order_id);
                $refund_sn = $res['data'];
            }elseif($order['pay_type']==4){
                //积分兑换支付支付
                $res = Finance::addDelUserCoin($order['uid'],$refund_money,1,"订单{$order['order_sn']}退款退回",6,$order_id);
                $refund_sn = $res['data'];
            }else{
                //支付宝或微信
                if(empty($refund_sn)){
                    $refund_sn = str_replace('_','',$order['order_sn']);
                    $refund_sn = 'R'.$refund_sn;
                }
            }
        }

        //更新退款单号
        $change['refund_sn'] = $refund_sn;

        if($type==1){
            if($order['refund_reason']!=''){
                $change['refund_reason'] = $order['refund_reason'].'-'.$reason;
            }else{
                $change['refund_reason'] = $reason;
            }
        }

        $save = Db::name('order')
            ->where('id','=',$order_id)
            ->where('status','=',-2)
            ->update($change);
        if(!$save){
            throw new ServerException('订单状态保存失败');
        }

        //积分抵扣退回
        if($coin>0&&$order['uid']>0){
            Finance::addDelUserCoin($order['uid'],$coin,1,"订单{$order['order_sn']}退款退回",6,$order_id);
        }

        //线上退款
        if($refund_money>0){
            try{
                if($order['pay_type']==1){
                    //微信
                    if($order['is_mini_pay']){
                        $Wechatpay = new Wechatpay(2);
                    }else{
                        $Wechatpay = new Wechatpay(1);
                    }

                    //因为存在父订单合并支付的情况故订单号不一定和微信商户中商家订单号一致 所以退款一律使用 交易流水号
                    $Wechatpay->refund($order['transaction_id'],$refund_sn,$order['order_price'],$refund_money,$reason);
                }elseif($order['pay_type']==2){
                    //支付宝
                    $Alipay = new Alipay();
                    //因为存在父订单合并支付的情况故订单号不一定和支付宝商户中商家订单号一致 所以退款一律使用 交易流水号
                    $Alipay->refund('', $refund_money,$order['transaction_id'],$refund_sn,$reason);
                }
            }catch (\Exception $exception){
                throw new UserException('第三方退款提示：'.$exception->getMessage());
            }
        }

        //部分退款订单需要结算
        if($is_some_refund){
            Order::orderSettle($order);
        }

        if($order['uid']){
            Notice::systemSend(2,$order['uid'],'订单退款成功',"您的订单{$order['order_sn']}已原路退款到订单选择的支付方式，请注意查看",2,$order['id']);
        }
    }


}